(module metadata mzscheme
  (define-struct testcase (input output))
  (provide (struct testcase (input output)))
  
  (define-struct cat-meta (desc tests))
  (define default-metadata (make-cat-meta "No description" (list)))
  (provide (struct cat-meta (desc tests))
           default-metadata)
  
  (require "types/types.scm"
           "types/type-sugar.scm"
           "types/type-pprint.scm")
  
  ;; Store the pieces of information we have about a cat-function.
  ;; id is an identifier of the function that implements the given cat-func
  ;; and type is the type that was given (or inferred) for the function
  (define-struct cat-func (id type metadata))
  (provide (struct cat-func (id type metadata)))
  
  ;; Define some helper functions for manipulating the Cat environment.  This
  ;; can probably be merged into either the core or support, but since it is
  ;; used for syntax, it was easier to just put it here.
  (define env (make-hash-table))
  (define (cat-extend! key def) (hash-table-put! env key def))
  (define (cat-ref key failure-thunk) (hash-table-get env key failure-thunk))
  (provide cat-extend! cat-ref)
    
  ;; Function to provide a descriptive string for the given cat function
  (define (descriptive-string name func)
    (format "Name: ~s~%Type: ~A~%Description: ~A~%"
            name (type->string (cat-func-type func)) 
            (cat-meta-desc (cat-func-metadata func))))
  
  (define (describe-sym prim-sym)
    (let* ((func (cat-ref prim-sym #f)))
      (if func
          (display (descriptive-string prim-sym func))
          (display (format "Prim ~s is undefined" prim-sym)))))
  (provide describe-sym)
  
  ;; Macros for parsing the metadata
  (define (parse-test stx)
    (syntax-case stx ()
      ((_ ((in ...) => (out ...)))
       #'(make-testcase'(in ...) (out ...)))))
  
  (define (parse-metadata stx)
    (syntax-case stx (desc tests)
      (((desc str ...) (tests test ...))
       #'(make-cat-meta (string-append str ...) (list (parse-test test) ...)))
      (((desc str ...))
       #'(make-cat-meta (string-append str ...) (list)))
      (((tests test ...))
       #'(make-cat-meta "No Description" (list (parse-test test) ...)))
      (((tests test ...) (desc str ...))
       #'(make-cat-meta  (string-append str ...) (list (parse-test test) ...)))
      (()
       #'(make-cat-meta "No Description" (list)))))
  (provide parse-metadata)
  )
